package cn.sciento.boot.data.change.dto;

import java.util.List;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.SqlCommandType;
import cn.sciento.boot.data.change.utils.JsqlParserUtil;

public class SqlParserInfo {
  private String sql;
  
  private SqlCommandType sqlCommandType;
  
  private String tableName;
  
  private String schemaName;
  
  private Table table;
  
  private Expression whereExpression;
  
  private List<Column> columns;
  
  private Select select;
  
  private InsertType insertType;
  
  private Integer itemsListSize;
  
  private Statement statement;
  
  public static SqlParserInfo getInstance(String sql, SqlCommandType sqlCommandType) throws JSQLParserException {
    SqlParserInfo sqlParserInfo = new SqlParserInfo();
    sqlParserInfo.sqlCommandType = sqlCommandType;
    if (StringUtils.isEmpty(sql))
      return sqlParserInfo; 
    Statement statement = CCJSqlParserUtil.parse(sql);
    sqlParserInfo.statement = statement;
    if (sqlCommandType == SqlCommandType.UPDATE) {
      Update updateStatement = (Update)statement;
      List<Table> updateTables = updateStatement.getTables();
      if (updateTables == null || updateTables.isEmpty())
        return sqlParserInfo; 
      sqlParserInfo.table = updateTables.get(0);
      sqlParserInfo.whereExpression = updateStatement.getWhere();
      sqlParserInfo.columns = updateStatement.getColumns();
    } else if (sqlCommandType == SqlCommandType.INSERT) {
      Insert insertStatement = (Insert)statement;
      Table insertTable = insertStatement.getTable();
      if (insertTable == null)
        return sqlParserInfo; 
      sqlParserInfo.select = insertStatement.getSelect();
      sqlParserInfo.table = insertTable;
      sqlParserInfo.whereExpression = null;
      sqlParserInfo.insertType = JsqlParserUtil.getInsertType(insertStatement);
      if (InsertType.BATCH_BY_VALUES.equals(sqlParserInfo.insertType)) {
        sqlParserInfo
          .itemsListSize = ((MultiExpressionList) insertStatement.getItemsList()).getExprList().size();
      } else if (InsertType.SINGLE.equals(sqlParserInfo.insertType)) {
        sqlParserInfo.itemsListSize = 1;
      } 
    } else if (sqlCommandType == SqlCommandType.DELETE) {
      Delete deleteStatement = (Delete)statement;
      Table deleteTable = deleteStatement.getTable();
      if (deleteTable == null)
        return sqlParserInfo; 
      sqlParserInfo.table = deleteTable;
      sqlParserInfo.whereExpression = deleteStatement.getWhere();
    } 
    sqlParserInfo.tableName = sqlParserInfo.table.getName();
    sqlParserInfo.schemaName = sqlParserInfo.table.getSchemaName();
    return sqlParserInfo;
  }
  
  public String getTableName() {
    return this.tableName;
  }
  
  public void setTableName(String tableName) {
    this.tableName = tableName;
  }
  
  public String getSchemaName() {
    return this.schemaName;
  }
  
  public void setSchemaName(String schemaName) {
    this.schemaName = schemaName;
  }
  
  public Table getTable() {
    return this.table;
  }
  
  public void setTable(Table table) {
    this.table = table;
  }
  
  public Expression getWhereExpression() {
    return this.whereExpression;
  }
  
  public void setWhereExpression(Expression whereExpression) {
    this.whereExpression = whereExpression;
  }
  
  public List<Column> getColumns() {
    return this.columns;
  }
  
  public void setColumns(List<Column> columns) {
    this.columns = columns;
  }
  
  public String getSql() {
    return this.sql;
  }
  
  public void setSql(String sql) {
    this.sql = sql;
  }
  
  public SqlCommandType getSqlCommandType() {
    return this.sqlCommandType;
  }
  
  public void setSqlCommandType(SqlCommandType sqlCommandType) {
    this.sqlCommandType = sqlCommandType;
  }
  
  public Select getSelect() {
    return this.select;
  }
  
  public void setSelect(Select select) {
    this.select = select;
  }
  
  public InsertType getInsertType() {
    return this.insertType;
  }
  
  public void setInsertType(InsertType insertType) {
    this.insertType = insertType;
  }
  
  public Integer getItemsListSize() {
    return this.itemsListSize;
  }
  
  public void setItemsListSize(Integer itemsListSize) {
    this.itemsListSize = itemsListSize;
  }
  
  public Statement getStatement() {
    return this.statement;
  }
  
  public void setStatement(Statement statement) {
    this.statement = statement;
  }
}
